package finance

class WaldWolfowitzService {
    
    static transactional = true
    def subtractService
    
    def totalRuns(changes) {
        def runs = 1	
        def posOrNeg = sign( changes[0] )
        
        for( i in 1..<changes.size()) {
            def currSign = sign( changes[i] )
            
            if(currSign != posOrNeg && currSign != 0) 
                runs++
            
            posOrNeg = currSign
        }
        
        return runs
    }
    
    def sign(val) {
        def posNegOr0 = 0
        
        if(val < 0)
            posNegOr0 = -1
        if(val > 0)
            posNegOr0 = 1
        
        return posNegOr0
    }
    
    def neg(changes) {
        def negList = changes.findAll { it < 0 }	
        return negList.size()
    }
    
    def pos(changes) {
        def posList = changes.findAll { it > 0 }	
        return posList.size()
    }
    
    def Z(list) {
        def deltas = subtractService.minPrev(list)	
        def minuses = neg(deltas)	
        def pluses = pos(deltas)
        def runs = totalRuns(deltas)
        def expected = expectedRuns( minuses, pluses)
        def deviation = stddev(minuses,pluses)
        
        return (runs - expected) / deviation
    }
    
    def expectedRuns(n1, n2) {
        return 2 * n1 * n2 / (n1 + n2) + 1
    }
    
    def stddev(n1, n2) {
        def product = n1 * n2
        def up = 2 * product * (2 * product  - n1 - n2)	
        
        def sum = n1 + n2
        def down = sum * sum * ( sum - 1)
        
        return Math.sqrt( up / down )
    }
}
